"""
Pydantic schemas for call tree data validation and serialization.
"""

from datetime import datetime
from typing import Dict, Any, List, Optional
from pydantic import BaseModel, Field, validator


class CallTreeSchema(BaseModel):
    """Schema for call tree data."""
    
    id: Optional[str] = None
    root_node_id: Optional[str] = None
    analysis_type: str = Field(default="unknown", description="Type of analysis performed")
    language: str = Field(default="unknown", description="Programming language")
    project_path: Optional[str] = Field(None, description="Path to project root")
    
    # Tree statistics
    total_nodes: int = Field(default=0, ge=0, description="Total number of nodes in tree")
    max_depth: int = Field(default=0, ge=0, description="Maximum depth of call tree")
    
    # Timestamps
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
    
    # Additional metadata
    metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
    
    class Config:
        """Pydantic configuration."""
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }
        validate_assignment = True
        
    @validator('analysis_type')
    def validate_analysis_type(cls, v):
        """Validate analysis type."""
        allowed_types = ['unknown', 'full_project', 'single_file', 'function_trace', 'dependency_analysis']
        if v not in allowed_types:
            raise ValueError(f'analysis_type must be one of: {", ".join(allowed_types)}')
        return v
    
    @validator('language')
    def validate_language(cls, v):
        """Validate language."""
        allowed_languages = ['unknown', 'python', 'cpp', 'c', 'fortran', 'typescript', 'javascript', 'latex', 'markdown']
        if v not in allowed_languages:
            raise ValueError(f'language must be one of: {", ".join(allowed_languages)}')
        return v


class CallTreeCreateSchema(BaseModel):
    """Schema for creating new call trees."""
    
    analysis_type: str = Field(description="Type of analysis to perform")
    language: str = Field(description="Programming language")
    project_path: Optional[str] = Field(None, description="Path to project root")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
    
    @validator('analysis_type')
    def validate_analysis_type(cls, v):
        """Validate analysis type."""
        allowed_types = ['full_project', 'single_file', 'function_trace', 'dependency_analysis']
        if v not in allowed_types:
            raise ValueError(f'analysis_type must be one of: {", ".join(allowed_types)}')
        return v


class CallTreeUpdateSchema(BaseModel):
    """Schema for updating call trees."""
    
    root_node_id: Optional[str] = None
    analysis_type: Optional[str] = None
    language: Optional[str] = None
    project_path: Optional[str] = None
    total_nodes: Optional[int] = Field(None, ge=0)
    max_depth: Optional[int] = Field(None, ge=0)
    metadata: Optional[Dict[str, Any]] = None


class CallTreeSummarySchema(BaseModel):
    """Schema for call tree summary data."""
    
    id: str
    analysis_type: str
    language: str
    project_path: Optional[str]
    total_nodes: int
    max_depth: int
    created_at: datetime
    updated_at: datetime
    
    class Config:
        """Pydantic configuration."""
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }


class CallTreeWithNodesSchema(CallTreeSchema):
    """Schema for call tree with associated nodes."""
    
    nodes: List['NodeSchema'] = Field(default_factory=list, description="Associated nodes")
    root_node: Optional['NodeSchema'] = Field(None, description="Root node of the tree")


# Forward references
from .node import NodeSchema
CallTreeWithNodesSchema.model_rebuild()